package org.fjsei.yewu.job.service;

import org.fjsei.yewu.job.controller.model.CreateJobDetailsRequestModel;
import org.fjsei.yewu.job.listener.BusinessHoursTriggerListener;
import org.fjsei.yewu.job.listener.JobHistoryListener;
import org.fjsei.yewu.job.util.Utility;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

@Component
@Slf4j
public class QuartzJobManager {

    private final Scheduler scheduler;

    //Inject the Spring Boot managed scheduler
    public QuartzJobManager(Scheduler scheduler) {
        this.scheduler = scheduler;

    }

    @PostConstruct
    public void addTriggerListener() throws SchedulerException {
        final ListenerManager listenerManager = scheduler.getListenerManager();
        listenerManager.addTriggerListener(new BusinessHoursTriggerListener());
        listenerManager.addJobListener(new JobHistoryListener());
    }
/*
Create or Update Job
* */
    public void createOrUpdateJob(CreateJobDetailsRequestModel req) throws SchedulerException {
        if(null!=req.getFrom() && null!=req.getTo()){
            for(int i=req.getFrom();i<=req.getTo();i++){
                createJobOfSeq(req,i);
            }
            return;
        }
        JobKey jobKey = JobKey.jobKey(req.getJobName(), req.getGroupName());
        try {
            JobDetail jobDetail = JobBuilder.newJob(Utility.getJobClass(req.getJobClassName()))
                    .withDescription(req.getDescription())
                    .withIdentity(req.getJobName(), req.getGroupName())
                    .requestRecovery().storeDurably() // 根据需要决定是否需要这些选项
                    .build();
            SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger()
                        .withIdentity(req.getJobName() + "Trigger", req.getGroupName())
                        .startNow() // Trigger 将立即触发
                        .forJob(jobKey) // 关联到指定的 JobDetail
                        .build();
            if (this.scheduler.checkExists(jobKey)) {
                List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
                for(Trigger trig : triggers) {
                    scheduler.unscheduleJob(trig.getKey());
                }
                this.scheduler.scheduleJob(trigger); // 注意：这实际上可能会导致多个 Trigger 关联到同一个 JobDetail，这可能不是您想要的
            } else {
                this.scheduler.scheduleJob(jobDetail, trigger); // 创建并调度新的 Job 和 Trigger
            }
        } catch (ClassNotFoundException classNotFoundException) {
            log.error("Job class not found {}", classNotFoundException.getException(), classNotFoundException);
            throw new SchedulerException("Job class not found " + req.getJobName(), classNotFoundException);
        }
    }
    //启用尾号序号的Job
    public void createJobOfSeq(CreateJobDetailsRequestModel createJobDetailsRequestModel, int index) throws SchedulerException {
        JobKey jobKey = JobKey.jobKey(createJobDetailsRequestModel.getJobName()+index, createJobDetailsRequestModel.getGroupName());
        try {
            JobDetail jobDetail = JobBuilder.newJob(Utility.getJobClass(createJobDetailsRequestModel.getJobClassName()))
                    .withDescription(createJobDetailsRequestModel.getDescription())
                    .withIdentity(createJobDetailsRequestModel.getJobName()+index, createJobDetailsRequestModel.getGroupName())
                    .requestRecovery().storeDurably() // 根据需要决定是否需要这些选项
                    .build();
            SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger()
                    .withIdentity(createJobDetailsRequestModel.getJobName()+index + "Trigger", createJobDetailsRequestModel.getGroupName())
                    .startNow() // Trigger 将立即触发
                    .forJob(jobKey) // 关联到指定的 JobDetail
                    .build();
            if (this.scheduler.checkExists(jobKey)) {
                List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
                for(Trigger trig : triggers) {
                    scheduler.unscheduleJob(trig.getKey());
                }
                this.scheduler.scheduleJob(trigger); // 注意：这实际上可能会导致多个 Trigger 关联到同一个 JobDetail，这可能不是您想要的
            } else {
                this.scheduler.scheduleJob(jobDetail, trigger); // 创建并调度新的 Job 和 Trigger
            }
        } catch (ClassNotFoundException classNotFoundException) {
            log.error("Job class not found {}", classNotFoundException.getException(), classNotFoundException);
            throw new SchedulerException("Job class not found " + createJobDetailsRequestModel.getJobName()+index, classNotFoundException);
        }
    }
    // Read Job
    public JobDetail getJobDetails(String jobName, String groupName) throws SchedulerException {
        return this.scheduler.getJobDetail(JobKey.jobKey(jobName, groupName));
    }

    // Delete Job
    public boolean deleteJob(CreateJobDetailsRequestModel req) throws SchedulerException {
        if(null!=req.getFrom() && null!=req.getTo()){
            for(int i=req.getFrom();i<=req.getTo();i++){
                this.scheduler.deleteJob(JobKey.jobKey(req.getJobName()+i, req.getGroupName()));
            }
            return true;
        }
        return false;
    }

    // Pause Job
    public boolean pauseJobAll(CreateJobDetailsRequestModel req) throws SchedulerException {
        if(null!=req.getFrom() && null!=req.getTo()){
            for(int i=req.getFrom();i<=req.getTo();i++){
                this.scheduler.interrupt(JobKey.jobKey(""+i, req.getGroupName()));        //新加！
                this.scheduler.pauseJob(JobKey.jobKey(""+i, req.getGroupName()));
            }
            return true;
        }
        return false;
    }

    public void pauseJob(String jobName, String groupName) throws SchedulerException {
        this.scheduler.interrupt(JobKey.jobKey(jobName, groupName));        //新加！
        this.scheduler.pauseJob(JobKey.jobKey(jobName, groupName));
    }

    // Resume Job
    public void resumeJob(String jobName, String groupName) throws SchedulerException {
        this.scheduler.resumeJob(JobKey.jobKey(jobName, groupName));
    }

    //Read All Jobs
    public Set<JobDetail> getAllJobDetails() throws SchedulerException {
        //Retrive all jobs keys from scheduler
        Set<JobKey> jobKeys = scheduler.getJobKeys(GroupMatcher.anyGroup());
        //Iterate through jobs keys and fetch JobDetail for each
        Set<JobDetail> jobDetailSet = jobKeys.stream().map(jobKey -> {
            try {
                return this.scheduler.getJobDetail(jobKey);
            } catch (SchedulerException e) {
                log.error("Exception occurred {}", e.getMessage(), e);
                return null;
            }
        }).filter(Objects::nonNull).collect(Collectors.toSet());
        return jobDetailSet;
    }
    //在重启之后需要手动去恢复的！
    public void pauseAll() throws SchedulerException {
        this.scheduler.pauseAll();
    }
    public void resumeAll() throws SchedulerException {
        this.scheduler.resumeAll();
    }
    public void shutdown() throws SchedulerException {
        this.scheduler.shutdown();
    }
    public void start() throws SchedulerException {
        this.scheduler.start();
    }
    public void clear() throws SchedulerException {
        this.scheduler.clear();
    }
}
